local L = LibStub("AceLocale-3.0"):GetLocale("AzCastBarOptions")
-- For patch 3.1 this code needs a slight change on line 96 & 100

local GetTime = GetTime;
local UnitAura = UnitAura;
local FormatTime = AzCastBar.FormatTime;

-- Variables
local b = AzCastBar.CreateBar();
local timers = {};
local frames = {};
local unit = "target";

-- Extra Options
local extraOptions = {
	{
		[0] = L["Additional"],
		{ type = "Check", var = "showBuffs", default = true, label = L["Show Target Buffs"] },
		{ type = "Check", var = "showDebuffs", default = true, label = L["Show Target Debuffs"], y = 16 },
		{ type = "Color", var = "colBuff", default = { 0.4, 0.6, 0.8, 1 }, label = L["Buff Color"] },
		{ type = "Color", var = "colDebuff", default = { 1.0, 0.5, 0.5, 1 }, label = L["Debuff Color"] },
	},
};

--------------------------------------------------------------------------------------------------------
--                                             Bar Scripts                                            --
--------------------------------------------------------------------------------------------------------

local function OnUpdate(self,elapsed)
	local timer = self.timer;
	self.timeLeft = max(0,timer.endTime - GetTime());
	self.status:SetValue(timer.duration == 0 and 0 or self.timeLeft);
	self.time:SetText(timer.duration == 0 and "" or (FormatTime(self.timeLeft)..(b.cfg.showTotalTime and " / "..FormatTime(timer.duration) or "")));
end

local function OnEnter(self)
	GameTooltip:SetOwner(self,"ANCHOR_RIGHT");
	GameTooltip:SetUnitAura(unit,self.timer.index,self.timer.debuff and "HARMFUL" or "HELPFUL");
end

local function HideGTT()
	GameTooltip:Hide();
end

--------------------------------------------------------------------------------------------------------
--                                                Code                                                --
--------------------------------------------------------------------------------------------------------

-- Configure Bar
local function ConfigureBar(bar,id)
	bar:EnableMouse(1);
	bar:SetScript("OnUpdate",OnUpdate);
	bar:SetScript("OnEnter",OnEnter);
	bar:SetScript("OnLeave",HideGTT);
	tinsert(b.bars,bar);
	AzCastBar.ApplyBarSettingsSpecific(b,id);
	return bar;
end

-- Update Timers
local function UpdateTimers()
	-- Loop Timers and update bars
	local bar;
	for index, table in ipairs(timers) do
		bar = b.bars[index] or ConfigureBar(AzCastBar.CreateBar(),index);
		bar.timer = table;
		bar.status:SetMinMaxValues(0,table.duration);
		bar.status:SetStatusBarColor(unpack(table.debuff and b.cfg.colDebuff or b.cfg.colBuff));
		bar.name:SetText(table.label..(table.count and table.count > 1 and " ("..table.count..")" or ""));
		bar.icon:SetTexture(table.icon);
		bar:Show();
	end
	-- Hide all other frames
	for i = #timers + 1, #b.bars do
		b.bars[i]:Hide();
	end
end

-- Sorts the buffs
local function SortBuffsFunc(a,b)
	if (a.debuff == b.debuff)then
		if (a.duration == 0) or (b.duration == 0) then
			if (a.duration == b.duration) then
				return a.label < b.label;
			else
				return a.duration < b.duration;
			end
		else
			return a.endTime > b.endTime;
		end
	else
		return tostring(a.debuff) > tostring(b.debuff);
	end
end

-- Query Buffs
local index;
local name, rank, icon, count, debuffType, duration, expirationTime, isMine;
local function QueryAuras(auraType)
	index = 1;
	while (1) do
--		name, rank, icon, count, debuffType, duration, expirationTime, casterUnit, isStealable = UnitAura(unit,index,"HELPFUL");
		name, rank, icon, count, debuffType, duration, expirationTime, isMine = UnitAura(unit,index,auraType);
		if (not name) then
			break;
--		elseif (UnitIsUnit(casterUnit,"player")) then
		elseif (isMine) then
			tinsert(timers,{ index = index, label = name, icon = icon, count = count, debuffType = debuffType, duration = duration, endTime = expirationTime, debuff = (auraType == "HARMFUL" and 1) });
		end
		index = (index + 1);
	end
end

-- Scan Target Buffs
local function ScanTargetBuffs()
	wipe(timers);
	-- Query Auras
	if (b.cfg.showBuffs) then
		QueryAuras("HELPFUL");
	end
	if (b.cfg.showDebuffs) then
		QueryAuras("HARMFUL");
	end
	-- Sort & Update
	sort(timers,SortBuffsFunc);
	UpdateTimers();
end

--------------------------------------------------------------------------------------------------------
--                                           Event Handling                                           --
--------------------------------------------------------------------------------------------------------

-- OnEvent
local function OnEvent(self,event,p1,...)
	if (event ~= "UNIT_AURA" or p1 == unit) then
		ScanTargetBuffs();
	end
end

-- Config Change
function b:OnConfigChanged(cfg,barId)
	if (barId ~= 1) then
		return;
	elseif (cfg.enabled) then
		self:RegisterEvent("UNIT_AURA");
		self:RegisterEvent("PLAYER_TARGET_CHANGED");
		ScanTargetBuffs()
	else
		self:UnregisterAllEvents();
		wipe(timers);
		UpdateTimers();
	end
end

--------------------------------------------------------------------------------------------------------
--                                        Init AzCastBar Entry                                        --
--------------------------------------------------------------------------------------------------------

b.token = L["TargetAuras"];
b.options = extraOptions;
b.bars = {};
b:ClearAllPoints();
b:SetPoint("CENTER");
b:SetScript("OnEvent",OnEvent);
tinsert(AzCastBar.frames,b);
ConfigureBar(b,1);